package docsync.doclist;

import java.io.InputStream;
import org.apache.http.HttpResponse;

import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpDelete;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpPut;
import org.apache.http.entity.InputStreamEntity;

import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.util.EntityUtils;

import docsync.XmlFeed;

public class DocListRequest {
	private String _user;
	private String _pw;
	private ClientLogin _writely_login;
	private ClientLogin _wise_login;
	private HttpClient _client;

	/**
	 * 
	 * @param login
	 *            Must be already logged in
	 */
	public DocListRequest(String user, String pw) {
		_user = user;
		_pw = pw;
		_client = new DefaultHttpClient();
	}

	public HttpResponse get(String url) throws Exception {
		return _client.execute(makeLoggedGetRequest(url));
	}

	public String getString(String url) throws Exception {
		HttpResponse resp = get(url);
		if (resp.getStatusLine().getStatusCode() != 200)
			throw new Exception("Server response error");
		return EntityUtils.toString(resp.getEntity());
	}

	public String listFiles() throws Exception {
		return getString("https://docs.google.com/feeds/default/private/full?v=3");
	}

	public XmlFeed getXmlFeed() throws Exception {
		return new XmlFeed(listFiles());
	}

	public HttpClient getClient() {
		return _client;
	}

	private HttpGet makeLoggedGetRequest(String url) throws Exception {
		ClientLogin login = selectLogin(url);// auto login if not already

		HttpGet httpget = new HttpGet(url);
		httpget.setHeader("Authorization", "GoogleLogin auth="
				+ login.getAuthToken());
		return httpget;
	}

	private ClientLogin selectLogin(String url) throws Exception {
		String wiseServer = "spreadsheets.google.com";
		String writelyServer = "docs.google.com";

		ClientLogin login;
		if (url.indexOf(wiseServer) >= 0) {
			login = getWiseLogin();
		} else {
			assert (url.indexOf(writelyServer) >= 0);
			login = getWritelyLogin();
		}
		return login;
	}

	public ClientLogin getWritelyLogin() throws Exception {
		if (_writely_login == null) {
			_writely_login = new ClientLogin(_user, _pw, "writely");
			_writely_login.login();
		}
		return _writely_login;
	}

	public ClientLogin getWiseLogin() throws Exception {
		if (_wise_login == null) {
			_wise_login = new ClientLogin(_user, _pw, "wise");
			_wise_login.login();
		}
		return _wise_login;
	}

	public InputStream getStream(String url) throws Exception {
		HttpResponse resp = get(url);
		return resp.getEntity().getContent();
	}

	public InputStream export(String url, String format) throws Exception {
		String target = url + "&exportFormat=" + format;
		return getStream(target);
	}

	public void upload(String title, String contenttype, InputStream is,
			long length) throws Exception {
		// final String binaryOctetStream = "binary/octet-stream";
		final String url = "https://docs.google.com/feeds/default/private/full";
		HttpPost post = new HttpPost(url);
		post.setHeader("Slug", title);
		post.setHeader("GData-Version", "3.0");
		post.setHeader("Authorization", "GoogleLogin auth="
				+ selectLogin(url).getAuthToken());
		InputStreamEntity entity = new InputStreamEntity(is, length);
		entity.setContentType(contenttype);
		post.setEntity(entity);

		HttpResponse resp = _client.execute(post);
		if (resp.getStatusLine().getStatusCode() != 201) {
			throw new Exception("Upload Failed");
		}
		resp.getEntity().consumeContent();

	}

	public void update(String url, String title, String etag,
			String contenttype, InputStream is, long length) throws Exception {

		HttpPut put = new HttpPut(url);
		put.setHeader("Slug", title);
		put.setHeader("GData-Version", "3.0");
		put.setHeader("Authorization", "GoogleLogin auth="
				+ selectLogin(url).getAuthToken());
		put.setHeader("If-Match", etag);

		InputStreamEntity entity = new InputStreamEntity(is, length);
		entity.setContentType(contenttype);
		put.setEntity(entity);

		HttpResponse resp = _client.execute(put);
		if (resp.getStatusLine().getStatusCode() != 200) {
			//System.err.println(resp.getStatusLine().getStatusCode());
//			System.err.println(EntityUtils.toString(resp.getEntity()));
			throw new Exception("Update Failed");
		}
		resp.getEntity().consumeContent();
	}

	public void update(String url, String title, String contenttype,
			InputStream is, long length) throws Exception {
		update(url, title, "*", contenttype, is, length);
	}

	public void remove(String resourceId, String etag) throws Exception {
		final String url = "https://docs.google.com/feeds/default/private/full/"
				+ resourceId + "?delete=true";
		HttpDelete delete = new HttpDelete(url);
		delete.setHeader("GData-Version", "3.0");
		delete.setHeader("Authorization", "GoogleLogin auth="
				+ selectLogin(url).getAuthToken());
		delete.setHeader("If-Match", etag);

		HttpResponse resp = _client.execute(delete);
		if (resp.getStatusLine().getStatusCode() != 200) {
			throw new Exception("Delete Failed");
		}
		resp.getEntity().consumeContent();
	}

	public void remove(String resourceId) throws Exception {
		remove(resourceId, "*");
	}
}
